#include "stdafx.h"
/*
 *  SceneLoader.cpp
 *
 *  Created by Carl Schissler on 8/16/09.
 *  
 *  File contains the implementation for reading and writing XML-based 3D scene
 *  description files. The implementation includes a simple limited XML
 *  parser/generator and other functions which translate to/from a scene XML file.
 *  
 *  Feel free to use this code without credit to or permission from its author.
 *
 */
#include "SceneLoader.h"


#include <sstream>
#include <cstdio>
#include <stdexcept>
#include <sstream>
#include <string>
#include <iostream>


namespace scene
{



//##########################################################################################
//##########################################################################################
//############		
//############		XML Attribute Class
//############		
//##########################################################################################
//##########################################################################################




/// A class used to hold an XML node attribute name-value pair
class XMLAttribute
{
	public:
		
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Constructors
			
			
			
			
			/// Create a default nameless valueless attribute.
			inline XMLAttribute()
			{
			}
			
			
			
			
			/// Construct an attribute from name and value strings.
			inline XMLAttribute( const std::string& newName, const std::string& newValue )
				:	name( newName ),
					value( newValue )
			{
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Data Members
			
			
			
			
			/// The name of the attribute.
			std::string name;
			
			
			
			
			/// The value of the attribute.
			std::string value;
			
			
			
			
};




//##########################################################################################
//##########################################################################################
//############		
//############		XMLNode Class
//############		
//##########################################################################################
//##########################################################################################




/// A class representing an XML node which has children, attributes.
class XMLNode
{
	public:
		
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Constructors
			
			
			
			
			/// Create a default XMLNode with no attributes, tag name, or children.
			inline XMLNode()
			{
			}
			
			
			
			
			/// Create an XMLNode from a tag name.
			inline XMLNode( const std::string& tag )
				:	tag( tag )
			{
			}
			
			
			
			
			/// Create an XMLNode from a tag name and list of attributes.
			inline XMLNode( const std::string& tag, const std::vector<XMLAttribute>& newAttributes )
				:	tag( tag ),
					attributes( newAttributes )
			{
			}
			
			
			
			
			/// Create an XMLNode from a tag name, list of attributes, and list of children.
			inline XMLNode( const std::string& tag, const std::vector<XMLAttribute>& newAttributes,
							const std::vector<XMLNode*>& newChildren )
				:	tag( tag ),
					attributes( newAttributes ),
					children( newChildren )
			{
			}
			
			
			
			
			/// Create a deep copy of an XMLNode
			inline XMLNode( const XMLNode& node )
				:	tag( node.tag ),
					attributes( node.attributes )
			{
				for ( size_t i = 0; i < node.children.size(); i++ )
					children.push_back( new XMLNode( *node.children[i] ) );
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Destructor
			
			
			
			
			/// Destroy an XMLNode and recursively destroy all children.
			inline ~XMLNode()
			{
				for ( size_t i = 0; i < children.size(); i++ )
					delete children[i];
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Assignment Operator
			
			
			
			
			/// Assign the contents of one XMLNode to another.
			inline XMLNode& operator = ( const XMLNode& node )
			{
				if ( this != &node )
				{
					for ( size_t i = 0; i < children.size(); i++ )
						delete children[i];
					
					
					tag = node.tag;
					attributes = node.attributes;
					
					children.clear();
					
					for ( size_t i = 0; i < node.children.size(); i++ )
						children.push_back( new XMLNode( *node.children[i] ) );
				}
				
				return *this;
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Child Accessor Methods
			
			
			
			
			/// Get the first direct child of this node whose tag matches the input tag
			/**
			  * If no such node is found, NULL is returned.
			  */
			inline XMLNode* getFirstChildWithTag( const std::string& tag ) const
			{
				for ( size_t i = 0; i < children.size(); i++ )
				{
					if ( tag == children[i]->tag )
						return children[i];
				}
				
				return NULL;
			}
			
			
			
			
			/// Get all direct children of this node whose tag matches the input tag
			inline std::vector<XMLNode*> getChildrenWithTag( const std::string& tag ) const
			{
				std::vector<XMLNode*> result;
				
				for ( size_t i = 0; i < children.size(); i++ )
				{
					if ( tag == children[i]->tag )
						result.push_back( children[i] );
				}
				
				return result;
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Attribute Accessor Method
			
			
			
			
			/// Get the first attribute of this node whose name matches the input name
			/**
			  * If no such attribute is found, NULL is returned.
			  */
			inline const XMLAttribute* getFirstAttributeWithName( const std::string& name ) const
			{
				for ( size_t i = 0; i < attributes.size(); i++ )
				{
					if ( name == attributes[i].name )
						return &attributes[i];
				}
				
				return NULL;
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	String Conversion Method
			
			
			
			
			/// Get a string representing this XML node.
			inline std::string toString() const
			{
				return toString( 0 );
			}
			
			
			
			
			/// Get a string representing this XML node indented by the specified number of tabs.
			private: inline std::string toString( size_t indentationLevel ) const
			{
				if ( tag == "text" )
				{
					const XMLAttribute* text = getFirstAttributeWithName("text");
					
					if ( text != NULL )
						return text->value;
					else
						return std::string();
				}
				
				std::stringbuf buffer;
				
				for ( size_t i = 0; i < indentationLevel; i++ )
					buffer.sputc('\t');
				
				buffer.sputc( '<' );
				buffer.sputn( tag.c_str(), tag.length() );
				
				for ( size_t i = 0; i < attributes.size(); i++ )
				{
					buffer.sputc(' ');
					buffer.sputn( attributes[i].name.c_str(), attributes[i].name.length() );
					buffer.sputc('=');
					buffer.sputc('"');
					buffer.sputn( attributes[i].value.c_str(), attributes[i].value.length() );
					buffer.sputc('"');
				}
				
				buffer.sputc( '>' );
				buffer.sputc( '\n' );
				
				for ( size_t i = 0; i < children.size(); i++ )
				{
					std::string childString = children[i]->toString( indentationLevel + 1 );
					buffer.sputn( childString.c_str(), childString.length() );
					buffer.sputc( '\n' );
				}
				
				for ( size_t i = 0; i < indentationLevel; i++ )
					buffer.sputc('\t');
				
				buffer.sputc( '<' );
				buffer.sputc( '/' );
				buffer.sputn( tag.c_str(), tag.length() );
				buffer.sputc( '>' );
				
				return buffer.str();
			}
			public:
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Data Members
			
			
			
			
			/// A string representing the tag of this node.
			std::string tag;
			
			
			
			
			/// A list of attributes for this node.
			std::vector<XMLAttribute> attributes;
			
			
			
			
			/// A list of pointers to children of this node.
			std::vector<XMLNode*> children;
			
			
			
};




//##########################################################################################
//##########################################################################################
//############		
//############		XMLParser Class
//############		
//##########################################################################################
//##########################################################################################




class XMLParser
{
	public:
		
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Constructor
			
			
			
			
			/// Create a new XMLParser.
			inline XMLParser()
			{
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Parse Method
			
			
			
			
			/// Parse the input source string and return an XMLNode.
			inline XMLNode parse( const std::string& source ) throw(std::runtime_error)
			{
				currentCharacter = source.c_str();
				end = currentCharacter + source.length();
				currentLineNumber = 1;
				
				nextToken();
				
				std::vector<XMLNode*> result = parseScope();
				
				return XMLNode( "document", std::vector<XMLAttribute>(), result );
			}
			
			
			
	private:
		
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Private Token Class
			
			
			
			
			/// A class representing a token produced by an XML scanner.
			class Token
			{
				public:
					
					
					/// An enum representing the different types of tokens.
					typedef enum TokenType
					{
						LESS_THAN,
						END_TAG_START, // "</"
						LEAF_NODE_END, // "/>"
						GREATER_THAN,
						DOUBLE_QUOTE,
						EQUALS,
						IDENTIFIER,
						OTHER,
						WHITESPACE,
						COMMENT,
						END_OF_TEXT
					};
					
					
					/// Create a default token with END_OF_TEXT type.
					inline Token()
						:	type( END_OF_TEXT )
					{
					}
					
					
					/// Create a token with the specified type and no spelling.
					inline Token( TokenType newType )
						:	type( newType )
					{
					}
					
					
					/// Create a token with type and spelling.
					inline Token( TokenType newType, const std::string& newSpelling, size_t newLineNumber )
						:	type( newType ),
							spelling( newSpelling ),
							lineNumber( newLineNumber )
					{
					}
					
					
					/// The type of this token.
					TokenType type;
					
					
					/// The spelling of this token.
					std::string spelling;
					
					
					/// The line number of the start of the token.
					size_t lineNumber;
					
					
			};
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Scope Parse Method
			
			
			
			
			/// Parse an XML scope (the space between two nodes).
			std::vector<XMLNode*> parseScope() throw(std::runtime_error)
			{
				std::vector<XMLNode*> nodes;
				
				while ( currentToken.type != Token::END_OF_TEXT &&
						currentToken.type != Token::END_TAG_START )
				{
					if ( currentToken.type == Token::LESS_THAN )
						nodes.push_back( parseNode() );
					else
						nodes.push_back( parseText() );
				}
				
				return nodes;
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Node Parse Method
			
			
			
			
			/// Parse an XML node and return an object for it.
			XMLNode* parseNode() throw(std::runtime_error)
			{
				match( Token::LESS_THAN );
				
				check( Token::IDENTIFIER );
				std::string tag = currentToken.spelling;
				nextToken();
				
				std::vector<XMLAttribute> attributes = parseAttributeList();
				
				if ( currentToken.type == Token::LEAF_NODE_END )
				{
					// This is a leaf node, create and return it.
					nextToken();
					
					return new XMLNode( tag, attributes );
				}
				else
				{
					match( Token::GREATER_THAN );
					
					std::vector<XMLNode*> children = parseScope();
					
					match( Token::END_TAG_START );
					
					check( Token::IDENTIFIER );
					std::string tag2 = currentToken.spelling;
					
					if ( tag != tag2 )
						throw std::runtime_error("Start/end tag mismatch");
					
					nextToken();
					
					match( Token::GREATER_THAN );
					
					return new XMLNode( tag, attributes, children );
				}
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Text Parse Method
			
			
			
			
			/// Parse text contained within an XML node.
			/**
			  * An XMLNode is returned with the tag "text" which has
			  * the attribute "text" whose value is the text data.
			  */
			XMLNode* parseText() throw(std::runtime_error)
			{
				std::stringbuf buffer;
				
				while ( currentToken.type != Token::LESS_THAN &&
						currentToken.type != Token::END_TAG_START &&
						currentToken.type != Token::END_OF_TEXT )
				{
					// skip comments
					if ( currentToken.type == Token::COMMENT )
					{
						nextToken();
						continue;
					}
					
					// Append the token's spelling to the text node.
					buffer.sputn( currentToken.spelling.c_str(), currentToken.spelling.length() );
					
					nextToken();
					
					// If there is one more token, append a space to the buffer.
					if ( currentToken.type != Token::LESS_THAN &&
						currentToken.type != Token::END_TAG_START &&
						currentToken.type != Token::END_OF_TEXT )
						buffer.sputc( ' ' );
				}
				
				// Create the text data attribute
				std::vector<XMLAttribute> attributes;
				
				attributes.push_back( XMLAttribute( "text", buffer.str() ) );
				
				return new XMLNode( "text", attributes );
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Attribute List Parse Method
			
			
			
			
			/// Parse an attribute list and return a list of XMLAttribute objects.
			std::vector<XMLAttribute> parseAttributeList() throw(std::runtime_error)
			{
				std::vector<XMLAttribute> attributes;
				
				skipWhiteSpace();
				
				while ( currentToken.type == Token::IDENTIFIER )
				{
					std::string name = currentToken.spelling;
					
					nextToken();
					
					match( Token::EQUALS );
					match( Token::DOUBLE_QUOTE );
					
					std::stringbuf buffer;
					
					while ( currentToken.type != Token::DOUBLE_QUOTE &&
							currentToken.type != Token::END_OF_TEXT )
					{
						buffer.sputn( currentToken.spelling.c_str(), currentToken.spelling.length() );
						
						nextToken();
						
						if ( currentToken.type == Token::WHITESPACE )
						{
							buffer.sputc(' ');
							nextToken();
						}
					}
					
					attributes.push_back( XMLAttribute( name, buffer.str() ) );
					
					match( Token::DOUBLE_QUOTE );
					
					skipWhiteSpace();
				}
				
				return attributes;
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Token Match Checking Methods
			
			
			
			
			/// Make sure that the current token has the given type.
			/**
			  * If so, advance to the next token. If not, throw a runtime_error.
			  */
			inline void match( Token::TokenType type ) throw(std::runtime_error)
			{
				if ( currentToken.type == type )
				{
					nextToken();
				}
				else if ( currentToken.type == Token::WHITESPACE )
				{
					nextToken();
					
					if ( currentToken.type == type )
					{
						nextToken();
					}
					else
					{
						throw std::runtime_error("Line " + toString(currentToken.lineNumber) +
													": Expected " + getTokenTypeName(type) +
													" but found " + currentToken.spelling );
					}
				}
				else
				{
					throw std::runtime_error("Line " + toString(currentToken.lineNumber) +
													": Expected " + getTokenTypeName(type) +
													" but found " + currentToken.spelling );
				}
			}
			
			
			
			
			/// Make sure that the current token has the given type.
			/**
			  * If not, throw a runtime_error.
			  */
			inline void check( Token::TokenType type ) throw(std::runtime_error)
			{
				if ( currentToken.type != type )
				{
					if ( currentToken.type == Token::WHITESPACE )
					{
						nextToken();
						
						if ( currentToken.type != type )
							throw std::runtime_error("Line " + toString(currentToken.lineNumber) +
													": Expected " + getTokenTypeName(type) +
													" but found " + currentToken.spelling );
					}
					else
						throw std::runtime_error("Line " + toString(currentToken.lineNumber) +
													": Expected " + getTokenTypeName(type) +
													" but found " + currentToken.spelling );
				}
			}
			
			
			
			template < typename T >
			inline std::string toString( T number )
			{
				std::stringstream stream;
				
				stream << number;
				
				return stream.str();
			}
			
			
			
			inline void skipWhiteSpace()
			{
				while ( currentToken.type == Token::WHITESPACE )
					nextToken();
			}
			
			#define STRINGIFY( arg ) #arg
			
			
			inline std::string getTokenTypeName( Token::TokenType type ) const
			{
				switch ( type )
				{
					case Token::LESS_THAN: return std::string("<");
					case Token::GREATER_THAN: return std::string(">");
					case Token::END_TAG_START: return std::string("</");
					case Token::LEAF_NODE_END: return std::string("/>");
					case Token::DOUBLE_QUOTE: return std::string("\"");
					case Token::EQUALS: return std::string("=");
					case Token::IDENTIFIER: return std::string("identifier");
					case Token::OTHER: return std::string("other");
					case Token::WHITESPACE: return std::string("whitespace");
					case Token::END_OF_TEXT: return std::string("end of text");
					default:
						return std::string("error");
				}
			}
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Scan Next Token Method
			
			
			
			
			/// Set the currentToken data member to have the next token.
			inline void nextToken()
			{
				if ( currentCharacter == end )
					currentToken = Token( Token::END_OF_TEXT, "", currentLineNumber );
				
				if ( isWhiteSpace( *currentCharacter ) )
				{
					std::stringbuf buffer;
					buffer.sputc( *currentCharacter );
					
					if ( *currentCharacter == '\n' )
						currentLineNumber++;
					
					currentCharacter++;
					
					while ( currentCharacter != end && isWhiteSpace( *currentCharacter ) )
					{
						buffer.sputc( *currentCharacter );
						
						if ( *currentCharacter == '\n' )
							currentLineNumber++;
						
						currentCharacter++;
					}
					
					currentToken = Token( Token::WHITESPACE, buffer.str(), currentLineNumber );
					
					return;
				}
				else if ( isADigit( *currentCharacter ) || isALetter( *currentCharacter ) )
				{
					std::stringbuf buffer;
					buffer.sputc( *currentCharacter );
					
					currentCharacter++;
					
					while ( currentCharacter != end && 
							(isADigit( *currentCharacter ) || isALetter( *currentCharacter )) )
					{
						buffer.sputc( *currentCharacter );
						currentCharacter++;
						
					}
					
					currentToken = Token( Token::IDENTIFIER, buffer.str(), currentLineNumber );
					
					return;
				}
				
				// Determine the next token from the next character
				switch ( *currentCharacter )
				{
					case '<':
							currentCharacter++;
							
							if ( *currentCharacter == '/' )
							{
								// This is an end tag start token
								currentToken = Token( Token::END_TAG_START, "</", currentLineNumber );
								currentCharacter++;
								
								return;
							}
							else if ( *currentCharacter == '!' )
							{
								// This might be a comment
								currentCharacter++;
								
								if ( currentCharacter != end && *currentCharacter == '-' )
								{
									currentCharacter++;
									
									if ( currentCharacter != end && *currentCharacter == '-' )
									{
										// This is a comment.
										currentCharacter++;
										
										std::stringbuf buffer;
										
										int charactersFound = 0;
										
										while ( currentCharacter != end )
										{
											if ( charactersFound == 0 && *currentCharacter == '-' )
											{
												charactersFound++;
												currentCharacter++;
												continue;
											}
											else if ( charactersFound == 1 && *currentCharacter == '-' )
											{
												charactersFound++;
												currentCharacter++;
												continue;
											}
											else if ( charactersFound == 2 && *currentCharacter == '>' )
											{
												charactersFound++;
												currentCharacter++;
												break;
											}
											else if ( charactersFound > 0 )
											{
												buffer.sputn( currentCharacter - charactersFound, charactersFound );
											}
											
											if ( *currentCharacter == '\n' )
												currentLineNumber++;
											
											buffer.sputc( *currentCharacter );
											currentCharacter++;
										}
										
										currentToken = Token( Token::COMMENT, buffer.str(), currentLineNumber );
										return;
									}
									else
										currentCharacter--;
								}
								else
									currentCharacter--;
							}
							
							currentToken = Token( Token::LESS_THAN, "<", currentLineNumber );
						break;
						
					case '>':
							currentToken = Token( Token::GREATER_THAN, ">", currentLineNumber );
							currentCharacter++;
						break;
						
					case '"':
							currentToken = Token( Token::DOUBLE_QUOTE, "\"", currentLineNumber );
							currentCharacter++;
						break;
						
					case '=':
							currentToken = Token( Token::EQUALS, "=", currentLineNumber );
							currentCharacter++;
						break;
						
					case '\0':
							currentToken = Token( Token::END_OF_TEXT, "", currentLineNumber );
						break;
						
					case '/':
							currentCharacter++;
							
							if ( *currentCharacter == '>' )
							{
								// This is a leaf node end token
								currentCharacter++;
								currentToken = Token( Token::LEAF_NODE_END, "/>", currentLineNumber );
								return;
							}
							else
								currentToken = Token( Token::OTHER, "/", currentLineNumber );
						break;
					default:
							std::stringbuf buffer;
							buffer.sputc( *currentCharacter );
							
							currentCharacter++;
							
							currentToken = Token( Token::OTHER, buffer.str(), currentLineNumber );
						break;
				}
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Scaning Helper Methods
			
			
			
			
			/// Return whether or not the given character is a white space character.
			inline bool isWhiteSpace( char character )
			{
				return character == ' ' || character == '\t' || character == '\n' || character == '\r';
			}
			
			
			
			
			/// Return whether or not the given character is a letter (upper or lower case).
			inline bool isALetter( char character )
			{
				return (character >= 'a' && character <= 'z') || (character >= 'A' && character <= 'Z');
			}
			
			
			
			
			/// Return whether or not the given character is a digit (0-9).
			inline bool isADigit( char character )
			{
				return character >= '0' && character <= '9';
			}
			
			
			
			
		//********************************************************************************
		//********************************************************************************
		//********************************************************************************
		//******	Data Members
			
			
			
			
			/// The last token to be scanned.
			Token currentToken;
			
			
			
			
			/// A pointer to the current character being scanned.
			const char* currentCharacter;
			
			
			
			
			/// A pointer to just past the end of the source input string.
			const char* end;
			
			
			
			
			/// The current line number of the parser.
			size_t currentLineNumber;
			
			
			
			
};




//##########################################################################################
//##########################################################################################
//############		
//############		readFile Method
//############		
//##########################################################################################
//##########################################################################################




/// Read the file with the given file name and return its contents in a string.
static std::string readFile( const std::string& fileName )
{
	// Allocate a buffer to hold file data before it is append to string buffer.
	static const size_t bufferSize = 128;
	char buffer[bufferSize];
	
	// Try to open the file
	FILE* file = std::fopen( fileName.c_str(), "r" );
	
	if ( file == NULL )
		throw std::runtime_error( "Cannot open file" );
	
	std::stringbuf stringBuffer;
	size_t numberRead;
	
	do
	{
		numberRead = std::fread( buffer, sizeof(char), bufferSize, file );
		stringBuffer.sputn( buffer, numberRead );
	}
	while ( !std::feof( file ) );
	
	fclose( file );
	
	return stringBuffer.str();
}




//##########################################################################################
//##########################################################################################
//############		
//############		writeFile Method
//############		
//##########################################################################################
//##########################################################################################




/// Read the file with the given file name and return its contents in a string.
static void writeFile( const std::string& fileName, const std::string& text )
{
	// Try to open the file
	FILE* file = std::fopen( fileName.c_str(), "w" );
	
	if ( file == NULL )
		throw std::runtime_error( "Cannot open file for writing" );
	
	std::fwrite( text.c_str(), sizeof(char), text.length(), file );
	
	fclose( file );
}




//##########################################################################################
//##########################################################################################
//############		
//############		Attribute Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get the value for a floating point XML attribute value.
static float getFloatAttributeValue( const XMLNode& node, const std::string& attributeName, float defaultValue )
{
	const XMLAttribute* attribute = node.getFirstAttributeWithName(attributeName);
	
	if ( attribute != NULL )
	{
		std::istringstream stream(attribute->value);
		
		float result;
		
		if ( (stream >> result).fail() )
		{
			printf("Expected numerical value for attribute %s in %s node. Using default value of %f\n",
					attributeName.c_str(), node.tag.c_str(), defaultValue );
			
			return defaultValue;
		}
		else
			return result;
	}
	else
	{
		printf("Tried to find attribute %s in %s node but failed. Using default value of %f\n",
				attributeName.c_str(), node.tag.c_str(), defaultValue );
		
		return defaultValue;
	}
}




//##########################################################################################
//##########################################################################################
//############		
//############		Color Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a color object from a color XML node.
static Color getColorFromNode( const XMLNode& node )
{
	if ( node.tag == "color" )
	{
		float r = getFloatAttributeValue( node, "r", 0.0f );
		float g = getFloatAttributeValue( node, "g", 0.0f );
		float b = getFloatAttributeValue( node, "b", 0.0f );
		float a = getFloatAttributeValue( node, "a", 1.0f );
		
		return Color( r, g, b, a );
	}
	else
		throw std::runtime_error("Cannot get color from a non-color XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Material Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a material object from a material XML node.
static Material getMaterialFromNode( const XMLNode& node )
{
	if ( node.tag == "material" )
	{
		float reflectance = getFloatAttributeValue( node, "reflectance", 0.0f );
		float refraction = getFloatAttributeValue( node, "refraction", 1.0f );
		float phongExponent = getFloatAttributeValue( node, "phongExponent", 16.0f );
		
		return Material( reflectance, refraction, phongExponent );
	}
	else
		throw std::runtime_error("Cannot get material from a non-material XML node");
}





//##########################################################################################
//##########################################################################################
//############		
//############		Normal Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a normal object from a normal XML node.
static Normal getNormalFromNode( const XMLNode& node )
{
	if ( node.tag == "normal" )
	{
		float x = getFloatAttributeValue( node, "x", 1.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		
		return Normal( x, y, z );
	}
	else
		throw std::runtime_error("Cannot get normal from a non-normal XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Vertex Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a vertex object from a vertex XML node.
static Vertex getVertexFromNode( const XMLNode& node, const Color& defaultColor, const Normal& defaultNormal )
{
	if ( node.tag == "vertex" )
	{
		XMLNode* colorNode = node.getFirstChildWithTag("color");
		
		Color color = defaultColor;
		
		if ( colorNode != NULL )
			color = getColorFromNode( *colorNode );
		
		XMLNode* normalNode = node.getFirstChildWithTag("normal");
		
		Normal normal = defaultNormal;
		
		if ( normalNode != NULL )
			normal = getNormalFromNode( *normalNode );
		
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		float u = getFloatAttributeValue( node, "u", 0.0f );
		float v = getFloatAttributeValue( node, "v", 0.0f );
		
		return Vertex( x, y, z, color, u, v, normal );
	}
	else
		throw std::runtime_error("Cannot get vertex from a non-vertex XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Transform Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a transform object from a transform XML node.
static Transform getTransformFromNode( const XMLNode& node )
{
	if ( node.tag == "transform" )
	{
		std::vector<Transform::Node> transforms;
		
		for ( size_t i = 0; i < node.children.size(); i++ )
		{
			if ( node.children[i]->tag == "scale" )
			{
				const XMLNode& scaleNode = *node.children[i];
				
				Transform::Node transform;
				
				transform.scaleX = getFloatAttributeValue( scaleNode, "x", 1.0f );
				transform.scaleY = getFloatAttributeValue( scaleNode, "y", 1.0f );
				transform.scaleZ = getFloatAttributeValue( scaleNode, "z", 1.0f );
				
				transforms.push_back( transform );
			}
			else if ( node.children[i]->tag == "rotate" )
			{
				const XMLNode& rotateNode = *node.children[i];
				
				Transform::Node transform;
				
				transform.axisX = getFloatAttributeValue( rotateNode, "axisX", 0.0f );
				transform.axisY = getFloatAttributeValue( rotateNode, "axisY", 0.0f );
				transform.axisZ = getFloatAttributeValue( rotateNode, "axisZ", 0.0f );
				transform.degrees = getFloatAttributeValue( rotateNode, "degrees", 0.0f );
				
				transforms.push_back( transform );
			}
			else if ( node.children[i]->tag == "translate" )
			{
				const XMLNode& translateNode = *node.children[i];
				
				Transform::Node transform;
				
				transform.x = getFloatAttributeValue( translateNode, "x", 0.0f );
				transform.y = getFloatAttributeValue( translateNode, "y", 0.0f );
				transform.z = getFloatAttributeValue( translateNode, "z", 0.0f );
				
				transforms.push_back( transform );
			}
		}
		
		return Transform( transforms );
	}
	else
		throw std::runtime_error("Cannot get transform from a non-transform XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Triangle Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a triangle object from a triangle XML node.
static Triangle getTriangleFromNode( const XMLNode& node, const Color& defaultColor,
									const Material& defaultMaterial )
{
	if ( node.tag == "triangle" )
	{
		// Does the triangle have a material node?
		XMLNode* materialNode = node.getFirstChildWithTag("material");
		
		Material material( defaultMaterial );
		
		if ( materialNode != NULL )
			material = getMaterialFromNode( *materialNode );
		
		// Does the triangle have a normal child node?
		XMLNode* normalNode = node.getFirstChildWithTag("normal");
		
		Normal normal;
		
		if ( normalNode != NULL )
			normal = getNormalFromNode( *normalNode );
		
		std::vector<Vertex> vertices;
		
		// Does the triangle have child color nodes?
		std::vector<XMLNode*> colorNodes = node.getChildrenWithTag("color");
		
		for ( size_t i = 0; i < colorNodes.size(); i++ )
		{
			// Does the color node have vertex children?
			std::vector<XMLNode*> vertexNodes = colorNodes[i]->getChildrenWithTag("vertex");
			
			Color color = getColorFromNode( *colorNodes[i] );
			
			for ( size_t j = 0; j < vertexNodes.size(); j++ )
				vertices.push_back( getVertexFromNode( *vertexNodes[j], color, normal ) );
		}
		
		// Get all direct child vertices
		
		std::vector<XMLNode*> vertexNodes = node.getChildrenWithTag("vertex");
		
		for ( size_t i = 0; i < vertexNodes.size(); i++ )
			vertices.push_back( getVertexFromNode( *vertexNodes[i], defaultColor, normal ) );
		
		if ( vertices.size() < 3 )
			throw std::runtime_error("Not enough vertices to make a triangle");
		else if ( vertices.size() > 3 )
			printf("Too many vertices for triangle, discarding extras");
		
		return Triangle( vertices[0], vertices[1], vertices[2], material );
	}
	else
		throw std::runtime_error("Cannot get triangle from a non-triangle XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Mesh Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a mesh object from a mesh XML node.
static Mesh getMeshFromNode( const XMLNode& node )
{
	if ( node.tag == "mesh" )
	{
		std::vector<Triangle> triangles;
		Color defaultColor( 1.0f, 1.0f, 1.0f );
		Material defaultMaterial;
		
		// Does the mesh have child color nodes?
		std::vector<XMLNode*> colorNodes = node.getChildrenWithTag("color");
		
		for ( size_t i = 0; i < colorNodes.size(); i++ )
		{
			// Does the color node have triangle children?
			std::vector<XMLNode*> triangleNodes = colorNodes[i]->getChildrenWithTag("triangle");
			
			Color color = getColorFromNode( *colorNodes[i] );
			
			for ( size_t j = 0; j < triangleNodes.size(); j++ )
				triangles.push_back( getTriangleFromNode( *triangleNodes[j], color, defaultMaterial ) );
			
			// Does the color have child material nodes?
			std::vector<XMLNode*> materialNodes = colorNodes[i]->getChildrenWithTag("material");
			
			for ( size_t i = 0; i < materialNodes.size(); i++ )
			{
				// Does the material node have triangle children?
				std::vector<XMLNode*> triangleNodes2 = materialNodes[i]->getChildrenWithTag("triangle");
				
				Material material = getMaterialFromNode( *materialNodes[i] );
				
				for ( size_t j = 0; j < triangleNodes2.size(); j++ )
					triangles.push_back( getTriangleFromNode( *triangleNodes2[j], color, material ) );
			}
		}
		
		// Does the mesh have child material nodes?
		std::vector<XMLNode*> materialNodes = node.getChildrenWithTag("material");
		
		for ( size_t i = 0; i < materialNodes.size(); i++ )
		{
			// Does the material node have triangle children?
			std::vector<XMLNode*> triangleNodes = materialNodes[i]->getChildrenWithTag("triangle");
			
			Material material = getMaterialFromNode( *materialNodes[i] );
			
			for ( size_t j = 0; j < triangleNodes.size(); j++ )
				triangles.push_back( getTriangleFromNode( *triangleNodes[j], defaultColor, material ) );
			
			// Does the material node have color children?
			std::vector<XMLNode*> colorNodes2 = materialNodes[i]->getChildrenWithTag("color");
			
			for ( size_t i = 0; i < colorNodes2.size(); i++ )
			{
				// Does the color node have triangle children?
				std::vector<XMLNode*> triangleNodes2 = colorNodes2[i]->getChildrenWithTag("triangle");
				
				Color color = getColorFromNode( *colorNodes2[i] );
				
				for ( size_t j = 0; j < triangleNodes2.size(); j++ )
					triangles.push_back( getTriangleFromNode( *triangleNodes2[j], color, material ) );
			}
		}
		
		
		// Get all direct child triangles
		std::vector<XMLNode*> triangleNodes = node.getChildrenWithTag("triangle");
		
		for ( size_t i = 0; i < triangleNodes.size(); i++ )
			triangles.push_back( getTriangleFromNode( *triangleNodes[i], defaultColor, defaultMaterial ) );
		
		
		// Does the mesh have a transformation specified?
		XMLNode* transformNode = node.getFirstChildWithTag("transform");
		
		Transform transform;
		
		if ( transformNode )
			transform = getTransformFromNode( *transformNode );
		
		// Get the name of the mesh
		const XMLAttribute* nameAttribute = node.getFirstAttributeWithName("name");
		
		std::string name = nameAttribute != NULL ? nameAttribute->value : "";
		
		return Mesh( triangles, transform, name );
	}
	else
		throw std::runtime_error("Cannot get mesh from a non-mesh XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Sphere Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a sphere object from a sphere XML node.
static Sphere getSphereFromNode( const XMLNode& node )
{
	if ( node.tag == "sphere" )
	{
		// Get the color of the sphere
		Color color( 1.0f, 1.0f, 1.0f );
		
		XMLNode* colorNode = node.getFirstChildWithTag("color");
		
		if ( colorNode != NULL )
			color = getColorFromNode( *colorNode );
		
		// Get the position and radius of the sphere
		float radius = getFloatAttributeValue( node, "radius", 1.0f );
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		
		// Get the material of the sphere.
		XMLNode* materialNode = node.getFirstChildWithTag("material");
		
		Material material;
		
		if ( materialNode != NULL )
			material = getMaterialFromNode( *materialNode );

		// read timecontroller
		std::vector<KeyFrame> KeyFrames;
		XMLNode* timeControllerNode = node.getFirstChildWithTag("timecontroller");
		if (timeControllerNode != NULL )
		{
			std::vector<XMLNode*> keys = timeControllerNode->getChildrenWithTag("key");
			for (size_t i = 0; i < keys.size(); ++i)
			{
				float time = getFloatAttributeValue( *keys[i], "time", 0.0f );
				float x = getFloatAttributeValue( *keys[i], "x", 0.0f );
				float y = getFloatAttributeValue( *keys[i], "y", 0.0f );
				float z = getFloatAttributeValue( *keys[i], "z", 0.0f );
				KeyFrames.push_back(scene::KeyFrame(time, x, y, z));
			}
		}
		
		return Sphere( radius, x, y, z, color, material, KeyFrames );
	}
	else
		throw std::runtime_error("Cannot get sphere from a non-sphere XML node");
}

static CSGUnion getCSGUnionFromNode( const XMLNode& node )
{
	if ( node.tag == "union" )
	{
		std::vector<XMLNode*> sphereNodes = node.getChildrenWithTag( "sphere" );

		if ( sphereNodes.size() < 2 )
		{
			throw std::runtime_error("Parsing error");
		}

		return CSGUnion(getSphereFromNode(*sphereNodes[0]), getSphereFromNode(*sphereNodes[1]));
	}
	else
		throw std::runtime_error("Cannot get union from a non-union XML node");
}

static CSGDifference getCSGDifferenceFromNode( const XMLNode& node )
{
	if ( node.tag == "difference" )
	{
		std::vector<XMLNode*> sphereNodes = node.getChildrenWithTag( "sphere" );

		if ( sphereNodes.size() < 2 )
		{
			throw std::runtime_error("Parsing error");
		}

		return CSGDifference(getSphereFromNode(*sphereNodes[0]), getSphereFromNode(*sphereNodes[1]));
	}
	else
		throw std::runtime_error("Cannot get difference from a non-difference XML node");
}

static CSGIntersection getCSGIntersectionFromNode( const XMLNode& node )
{
	if ( node.tag == "intersection" )
	{
		std::vector<XMLNode*> sphereNodes = node.getChildrenWithTag( "sphere" );

		if ( sphereNodes.size() < 2 )
		{
			throw std::runtime_error("Parsing error");
		}

		return CSGIntersection(getSphereFromNode(*sphereNodes[0]), getSphereFromNode(*sphereNodes[1]));
	}
	else
		throw std::runtime_error("Cannot get intersection from a non-intersection XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Light Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a light object from a light XML node.
static Light getLightFromNode( const XMLNode& node )
{
	if ( node.tag == "light" )
	{
		// Get the color of the light
		Color color( 1.0f, 1.0f, 1.0f );
		
		XMLNode* colorNode = node.getFirstChildWithTag("color");
		
		if ( colorNode != NULL )
			color = getColorFromNode( *colorNode );
		
		// Get the position of the light
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		float ambient = getFloatAttributeValue( node, "ambient", 0.0f );
		
		return Light( x, y, z, color, ambient );
	}
	else
		throw std::runtime_error("Cannot get light from a non-light XML node");
}

static DirectionalLight getDirectionalLightFromNode( const XMLNode& node )
{
	if ( node.tag == "directionalLight" )
	{
		// Get the color of the light
		Color color( 1.0f, 1.0f, 1.0f );

		XMLNode* colorNode = node.getFirstChildWithTag("color");

		if ( colorNode != NULL )
			color = getColorFromNode( *colorNode );

		// Get the position of the light
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		float ambient = getFloatAttributeValue( node, "ambient", 0.0f );

		float lookAtX = getFloatAttributeValue( node, "lookAtX", 0.0f );
		float lookAtY = getFloatAttributeValue( node, "lookAtY", 0.0f );
		float lookAtZ = getFloatAttributeValue( node, "lookAtZ", 0.0f );

		return DirectionalLight( x, y, z, lookAtX, lookAtY, lookAtZ, color, ambient );
	}
	else
		throw std::runtime_error("Cannot get light from a non-light XML node");
}

static SpotLight getSpotLightFromNode( const XMLNode& node )
{
	if ( node.tag == "spotLight" )
	{
		// Get the color of the light
		Color color( 1.0f, 1.0f, 1.0f );

		XMLNode* colorNode = node.getFirstChildWithTag("color");

		if ( colorNode != NULL )
			color = getColorFromNode( *colorNode );

		// Get the position of the light
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		float ambient = getFloatAttributeValue( node, "ambient", 0.0f );

		float lookAtX = getFloatAttributeValue( node, "lookAtX", 0.0f );
		float lookAtY = getFloatAttributeValue( node, "lookAtY", 0.0f );
		float lookAtZ = getFloatAttributeValue( node, "lookAtZ", 0.0f );

		float cutOff = getFloatAttributeValue( node, "cutOff", 0.0f );
		float exponent = getFloatAttributeValue( node, "exponent", 0.0f );

		return SpotLight( x, y, z, lookAtX, lookAtY, lookAtZ, color, ambient, cutOff, exponent );
	}
	else
		throw std::runtime_error("Cannot get light from a non-light XML node");
}


//##########################################################################################
//##########################################################################################
//############		
//############		Camera Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a light object from a light XML node.
static Camera getCameraFromNode( const XMLNode& node )
{
	if ( node.tag == "camera" )
	{
		// Get the field of view of the camera
		float fov = getFloatAttributeValue( node, "fov", 90.0f );
		
		// Get the position of the camera.
		float x = getFloatAttributeValue( node, "x", 0.0f );
		float y = getFloatAttributeValue( node, "y", 0.0f );
		float z = getFloatAttributeValue( node, "z", 0.0f );
		
		// Get the look at position of the camera.
		float lookAtX = getFloatAttributeValue( node, "lookAtX", 0.0f );
		float lookAtY = getFloatAttributeValue( node, "lookAtY", 0.0f );
		float lookAtZ = getFloatAttributeValue( node, "lookAtZ", 1.0f );
		
		// Get the up direction of the camera.
		float upX = getFloatAttributeValue( node, "upX", 0.0f );
		float upY = getFloatAttributeValue( node, "upY", 1.0f );
		float upZ = getFloatAttributeValue( node, "upZ", 0.0f );
		
		return Camera( fov, x, y, z, lookAtX, lookAtY, lookAtZ, upX, upY, upZ );
	}
	else
		throw std::runtime_error("Cannot get camera from a non-camera XML node");
}




//##########################################################################################
//##########################################################################################
//############		
//############		Instance Parse Method
//############		
//##########################################################################################
//##########################################################################################




/// Get a light object from a light XML node.
static Instance getInstanceFromNode( const XMLNode& node, const std::vector<Mesh>& meshes, 
										std::vector<Mesh>& meshResources )
{
	if ( node.tag == "instance" )
	{
		// Determine the name of the source object
		const XMLAttribute* classAttribute = node.getFirstAttributeWithName("class");
		
		// Does this instance point to anything?
		if ( classAttribute == NULL )
			return Instance();
		
		std::string sourceName = classAttribute->value;
		
		// Determine the name of the source object's file (if it exists).
		const XMLAttribute* fileAttribute = node.getFirstAttributeWithName("file");
		
		if ( fileAttribute != NULL )
		{
			// Load the mesh pointed to by this instance.
			Mesh mesh = loadMesh( fileAttribute->value );
			
			if ( mesh.name != sourceName )
			{
				printf("Instance points to invalid mesh name %s in file %s\n",
						sourceName.c_str(), fileAttribute->value.c_str() );
				return Instance();
			}
			else
			{
				// Make sure we don't already have a mesh with this name.
				bool foundMesh = false;
				
				for ( size_t i = 0; i < meshResources.size(); i++ )
				{
					if ( meshResources[i].name == mesh.name )
						foundMesh = true;
				}
				
				for ( size_t i = 0; i < meshes.size(); i++ )
				{
					if ( meshes[i].name == mesh.name )
						foundMesh = true;
				}
				
				if ( !foundMesh )
					meshResources.push_back( mesh );
				else
					printf("Duplicate mesh instance name %s encountered, Using first declaration.\n",
							mesh.name.c_str());
			}
		}
		else
		{
			// Make sure the instance refers to a mesh in the scene.
			
			bool foundMesh = false;
			
			for ( size_t i = 0; i < meshResources.size(); i++ )
			{
				if ( meshResources[i].name == sourceName )
					foundMesh = true;
			}
			
			for ( size_t i = 0; i < meshes.size(); i++ )
			{
				if ( meshes[i].name == sourceName )
					foundMesh = true;
			}
			
			// If not, warn the user.
			if ( !foundMesh )
				printf("Instance points to invalid mesh name %s\n", sourceName.c_str() );
		}
		
		// Does the instance have a transformation specified?
		XMLNode* transformNode = node.getFirstChildWithTag("transform");
		
		Transform transform;
		
		if ( transformNode )
			transform = getTransformFromNode( *transformNode );
		
		return Instance( sourceName, transform );
	}
	else
		throw std::runtime_error("Cannot get instance from a non-instance XML node\n");
}





//##########################################################################################
//##########################################################################################
//############		
//############		Load Scene Method
//############		
//##########################################################################################
//##########################################################################################



/// Load the scene contained in the XML file with the specified filename.
Scene loadScene( const std::string& fileName )
{
	try
	{
		// Parse the XML document
		XMLParser parser;
		
		XMLNode document = parser.parse( readFile( fileName ) );
		
		// Get the first scene node from the document
		XMLNode* sceneNode = document.getFirstChildWithTag( "scene" );
		
		if ( sceneNode == NULL )
			return Scene();
		
		// Get all meshes from the scene node
		std::vector<XMLNode*> meshNodes = sceneNode->getChildrenWithTag( "mesh" );
		std::vector<Mesh> meshes;
		
		for ( size_t i = 0; i < meshNodes.size(); i++ )
		{
			Mesh mesh = getMeshFromNode( *meshNodes[i] );
			
			bool foundMesh = false;
			
			for ( size_t j = 0; j < meshes.size(); j++ )
			{
				if ( mesh.name == meshes[j].name )
					foundMesh = true;
			}
			
			if ( foundMesh )
				printf("Found mesh with duplicate name %s\n",mesh.name.c_str());
			
			meshes.push_back( mesh );
		}
		
		// Get all resource meshes from the root node
		std::vector<XMLNode*> meshResourceNodes = document.getChildrenWithTag( "mesh" );
		std::vector<Mesh> meshResources;
		
		for ( size_t i = 0; i < meshResourceNodes.size(); i++ )
		{
			Mesh mesh = getMeshFromNode( *meshResourceNodes[i] );
			
			bool foundMesh = false;
			
			for ( size_t j = 0; j < meshResources.size(); j++ )
			{
				if ( mesh.name == meshResources[j].name )
					foundMesh = true;
			}
			
			for ( size_t j = 0; j < meshes.size(); j++ )
			{
				if ( mesh.name == meshes[j].name )
					foundMesh = true;
			}
			
			if ( foundMesh )
				printf("Found mesh with duplicate name %s\n",mesh.name.c_str());
			
			meshResources.push_back( mesh );
		}
		
		// Get all spheres from the scene node
		std::vector<XMLNode*> sphereNodes = sceneNode->getChildrenWithTag( "sphere" );
		std::vector<Sphere> spheres;
		
		for ( size_t i = 0; i < sphereNodes.size(); i++ )
			spheres.push_back( getSphereFromNode( *sphereNodes[i] ) );

		std::vector<XMLNode*> unionNodes = sceneNode->getChildrenWithTag( "union" );
		std::vector<CSGUnion> csgUnions;

		for ( size_t i = 0; i < unionNodes.size(); i++ )
			csgUnions.push_back( getCSGUnionFromNode( *unionNodes[i] ) );

		std::vector<XMLNode*> differenceNodes = sceneNode->getChildrenWithTag( "difference" );
		std::vector<CSGDifference> csgDifferences;

		for ( size_t i = 0; i < differenceNodes.size(); i++ )
			csgDifferences.push_back( getCSGDifferenceFromNode( *differenceNodes[i] ) );

		std::vector<XMLNode*> intersectionNodes = sceneNode->getChildrenWithTag( "intersection" );
		std::vector<CSGIntersection> csgIntersections;

		for ( size_t i = 0; i < intersectionNodes.size(); i++ )
			csgIntersections.push_back( getCSGIntersectionFromNode( *intersectionNodes[i] ) );
		
		// Get all lights from the scene node
		std::vector<XMLNode*> lightNodes = sceneNode->getChildrenWithTag( "light" );
		std::vector<Light> lights;
		
		for ( size_t i = 0; i < lightNodes.size(); i++ )
			lights.push_back( getLightFromNode( *lightNodes[i] ) );

		std::vector<XMLNode*> directionalLightNodes = sceneNode->getChildrenWithTag( "directionalLight" );
		std::vector<DirectionalLight> dirLights;
		for ( size_t i = 0; i < directionalLightNodes.size(); i++ )
			dirLights.push_back( getDirectionalLightFromNode( *directionalLightNodes[i] ) );

		std::vector<XMLNode*> spotLightNodes = sceneNode->getChildrenWithTag( "spotLight" );
		std::vector<SpotLight> spotLights;
		for ( size_t i = 0; i < spotLightNodes.size(); i++ )
			spotLights.push_back( getSpotLightFromNode( *spotLightNodes[i] ) );
		
		// Get all instances from the scene node
		std::vector<XMLNode*> instanceNodes = sceneNode->getChildrenWithTag( "instance" );
		std::vector<Instance> instances;
		
		for ( size_t i = 0; i < instanceNodes.size(); i++ )
			instances.push_back( getInstanceFromNode( *instanceNodes[i], meshes, meshResources ) );
		
		// Get the camera from the scene node
		XMLNode* cameraNode = sceneNode->getFirstChildWithTag( "camera" );
		
		Camera camera;
		
		if ( cameraNode )
			camera = getCameraFromNode( *cameraNode );
		
		// Return the scene object.
		return Scene( camera, meshes, meshResources, spheres, lights, dirLights, spotLights, instances, 
			csgUnions, csgDifferences, csgIntersections );
	}
	catch ( const std::runtime_error& e )
	{
		printf( "Error while loading scene with file name: %s\n", fileName.c_str() );
		printf( "Error: %s\n", e.what() );
		
		return Scene();
	}
	
	return Scene();
}





//##########################################################################################
//##########################################################################################
//############		
//############		Load Mesh Method
//############		
//##########################################################################################
//##########################################################################################




/// Load the mesh contained in the XML file with the specified filename.
Mesh loadMesh( const std::string& fileName )
{
	try
	{
		// Parse the XML document
		XMLParser parser;
		
		XMLNode document = parser.parse( readFile( fileName ) );
		
		// Get the first scene node from the document
		XMLNode* meshNode = document.getFirstChildWithTag( "mesh" );
		
		if ( meshNode == NULL )
			return Mesh();
		
		// Return the mesh object.
		return getMeshFromNode( *meshNode );
	}
	catch ( const std::runtime_error& e )
	{
		printf( "Error while loading mesh with file name: %s\n", fileName.c_str() );
		printf( "Error: %s\n", e.what() );
		
		return Mesh();
	}
	
	return Mesh();
}





//##########################################################################################
//##########################################################################################
//############		
//############		Save Scene Methods
//############		
//##########################################################################################
//##########################################################################################


template < typename T >
inline std::string toString( T number )
{
	std::stringstream stream;
	
	stream << number;
	
	return stream.str();
}




XMLNode* getNodeForColor( const Color& color )
{
	XMLNode* colorNode = new XMLNode("color");
	
	colorNode->attributes.push_back( XMLAttribute( "r", toString(color.r) ) );
	colorNode->attributes.push_back( XMLAttribute( "g", toString(color.g) ) );
	colorNode->attributes.push_back( XMLAttribute( "b", toString(color.b) ) );
	colorNode->attributes.push_back( XMLAttribute( "a", toString(color.a) ) );
	
	return colorNode;
}




XMLNode* getNodeForNormal( const Normal& normal )
{
	XMLNode* normalNode = new XMLNode("normal");
	
	normalNode->attributes.push_back( XMLAttribute( "x", toString(normal.x) ) );
	normalNode->attributes.push_back( XMLAttribute( "y", toString(normal.y) ) );
	normalNode->attributes.push_back( XMLAttribute( "z", toString(normal.z) ) );
	
	return normalNode;
}



XMLNode* getNodeForVertex( const Vertex& vertex )
{
	XMLNode* vertexNode = new XMLNode("vertex");
	
	vertexNode->attributes.push_back( XMLAttribute( "x", toString(vertex.x) ) );
	vertexNode->attributes.push_back( XMLAttribute( "y", toString(vertex.y) ) );
	vertexNode->attributes.push_back( XMLAttribute( "z", toString(vertex.z) ) );
	vertexNode->attributes.push_back( XMLAttribute( "u", toString(vertex.u) ) );
	vertexNode->attributes.push_back( XMLAttribute( "v", toString(vertex.v) ) );
	
	vertexNode->children.push_back( getNodeForColor( vertex.color ) );
	vertexNode->children.push_back( getNodeForNormal( vertex.normal ) );
	
	return vertexNode;
}




XMLNode* getNodeForMaterial( const Material& material )
{
	XMLNode* materialNode = new XMLNode("material");
	
	materialNode->attributes.push_back( XMLAttribute( "reflectance", toString(material.reflectance) ) );
	materialNode->attributes.push_back( XMLAttribute( "refraction", toString(material.refraction) ) );
	materialNode->attributes.push_back( XMLAttribute( "phongExponent", toString(material.phongExponent) ) );
	
	return materialNode;
}




XMLNode* getNodeForTriangle( const Triangle& triangle )
{
	XMLNode* triangleNode = new XMLNode("triangle");
	
	triangleNode->children.push_back( getNodeForVertex( triangle.v[0] ) );
	triangleNode->children.push_back( getNodeForVertex( triangle.v[1] ) );
	triangleNode->children.push_back( getNodeForVertex( triangle.v[2] ) );
	triangleNode->children.push_back( getNodeForMaterial( triangle.material ) );
	
	return triangleNode;
}




XMLNode* getNodeForTransform( const Transform& transform )
{
	XMLNode* transformNode = new XMLNode("transform");
	
	for ( size_t i = 0; i < transform.nodes.size(); i++ )
	{
		// Emit a child "scale" node for any scaling that may occur.
		{
			XMLNode* scaleNode = new XMLNode("scale");
			
			scaleNode->attributes.push_back( XMLAttribute( "x", toString(transform.nodes[i].scaleX) ) );
			scaleNode->attributes.push_back( XMLAttribute( "y", toString(transform.nodes[i].scaleY) ) );
			scaleNode->attributes.push_back( XMLAttribute( "z", toString(transform.nodes[i].scaleZ) ) );
			
			transformNode->children.push_back( scaleNode );
		}
		
		// Emit a child "rotate" node for any rotation that may occur.
		{
			XMLNode* rotateNode = new XMLNode("rotate");
			
			rotateNode->attributes.push_back( XMLAttribute( "axisX", toString(transform.nodes[i].axisX) ) );
			rotateNode->attributes.push_back( XMLAttribute( "axisY", toString(transform.nodes[i].axisY) ) );
			rotateNode->attributes.push_back( XMLAttribute( "axisZ", toString(transform.nodes[i].axisZ) ) );
			rotateNode->attributes.push_back( XMLAttribute( "degrees", toString(transform.nodes[i].degrees) ) );
			
			transformNode->children.push_back( rotateNode );
		}
		
		// Emit a child "translate" node for any translation that may occur.
		{
			XMLNode* translateNode = new XMLNode("translate");
			
			translateNode->attributes.push_back( XMLAttribute( "x", toString(transform.nodes[i].x) ) );
			translateNode->attributes.push_back( XMLAttribute( "y", toString(transform.nodes[i].y) ) );
			translateNode->attributes.push_back( XMLAttribute( "z", toString(transform.nodes[i].z) ) );
			
			transformNode->children.push_back( translateNode );
		}
	}
	
	return transformNode;
}




void saveScene( const Scene& scene, const std::string& fileName )
{
	// Create XML nodes for the elements of the scene.
	XMLNode sceneNode("scene");
	
	// Create nodes for the camera in the scene.
	{
		XMLNode* cameraNode = new XMLNode("camera");
		
		cameraNode->attributes.push_back( XMLAttribute( "fov", toString(scene.camera.fov) ) );
		cameraNode->attributes.push_back( XMLAttribute( "x", toString(scene.camera.x) ) );
		cameraNode->attributes.push_back( XMLAttribute( "y", toString(scene.camera.y) ) );
		cameraNode->attributes.push_back( XMLAttribute( "z", toString(scene.camera.z) ) );
		cameraNode->attributes.push_back( XMLAttribute( "lookAtX", toString(scene.camera.lookAtX) ) );
		cameraNode->attributes.push_back( XMLAttribute( "lookAtY", toString(scene.camera.lookAtY) ) );
		cameraNode->attributes.push_back( XMLAttribute( "lookAtZ", toString(scene.camera.lookAtZ) ) );
		cameraNode->attributes.push_back( XMLAttribute( "upX", toString(scene.camera.upX) ) );
		cameraNode->attributes.push_back( XMLAttribute( "upY", toString(scene.camera.upY) ) );
		cameraNode->attributes.push_back( XMLAttribute( "upZ", toString(scene.camera.upZ) ) );
		
		sceneNode.children.push_back( cameraNode );
	}
	
	// Create nodes for all of the spheres in the scene.
	for ( size_t i = 0; i < scene.spheres.size(); i++ )
	{
		XMLNode* sphereNode = new XMLNode("sphere");
		
		sphereNode->attributes.push_back( XMLAttribute( "radius", toString(scene.spheres[i].radius) ) );
		sphereNode->attributes.push_back( XMLAttribute( "x", toString(scene.spheres[i].x) ) );
		sphereNode->attributes.push_back( XMLAttribute( "y", toString(scene.spheres[i].y) ) );
		sphereNode->attributes.push_back( XMLAttribute( "z", toString(scene.spheres[i].z) ) );
		sphereNode->children.push_back( getNodeForColor( scene.spheres[i].color ) );
		sphereNode->children.push_back( getNodeForMaterial( scene.spheres[i].material ) );
		
		sceneNode.children.push_back( sphereNode );
	}
	
	// Create nodes for all of the lights in the scene.
	for ( size_t i = 0; i < scene.lights.size(); i++ )
	{
		XMLNode* lightNode = new XMLNode("light");
		
		lightNode->attributes.push_back( XMLAttribute( "x", toString(scene.lights[i].x) ) );
		lightNode->attributes.push_back( XMLAttribute( "y", toString(scene.lights[i].y) ) );
		lightNode->attributes.push_back( XMLAttribute( "z", toString(scene.lights[i].z) ) );
		lightNode->attributes.push_back( XMLAttribute( "ambient", toString(scene.lights[i].ambient) ) );
		lightNode->children.push_back( getNodeForColor( scene.lights[i].color ) );
		
		sceneNode.children.push_back( lightNode );
	}
	
	// Create nodes for all of the meshes in the scene.
	for ( size_t i = 0; i < scene.meshes.size(); i++ )
	{
		XMLNode* meshNode = new XMLNode("mesh");
		
		for ( size_t j = 0; j < scene.meshes[i].triangles.size(); j++ )
			meshNode->children.push_back( getNodeForTriangle( scene.meshes[i].triangles[j] ) );
		
		if ( scene.meshes[i].name != "" )
			meshNode->attributes.push_back( XMLAttribute( "name", toString(scene.meshes[i].name) ) );
		
		meshNode->children.push_back( getNodeForTransform( scene.meshes[i].transform ) );
		
		sceneNode.children.push_back( meshNode );
	}
	
	// Create nodes for all of the instances in the scene.
	for ( size_t i = 0; i < scene.instances.size(); i++ )
	{
		XMLNode* instanceNode = new XMLNode("instance");
		
		instanceNode->attributes.push_back( XMLAttribute( "class", toString(scene.instances[i].sourceName) ) );
		instanceNode->children.push_back( getNodeForTransform( scene.instances[i].transform ) );
		
		sceneNode.children.push_back( instanceNode );
	}
	
	std::string sceneNodeString = sceneNode.toString();
	
	// Create nodes for all of the mesh resources in the scene.
	for ( size_t i = 0; i < scene.meshResources.size(); i++ )
	{
		XMLNode meshNode("mesh");
		
		for ( size_t j = 0; j < scene.meshResources[i].triangles.size(); j++ )
			meshNode.children.push_back( getNodeForTriangle( scene.meshResources[i].triangles[j] ) );
		
		if ( scene.meshResources[i].name != "" )
			meshNode.attributes.push_back( XMLAttribute( "name", toString(scene.meshResources[i].name) ) );
		
		meshNode.children.push_back( getNodeForTransform( scene.meshResources[i].transform ) );
		
		sceneNodeString = sceneNodeString + "\n" + meshNode.toString();
	}
	
	writeFile( fileName, sceneNodeString );
}





void saveMesh( const Mesh& mesh, const std::string& fileName )
{
	// Create an XML mode for the mesh.
	XMLNode meshNode("mesh");
	
	for ( size_t j = 0; j < mesh.triangles.size(); j++ )
		meshNode.children.push_back( getNodeForTriangle( mesh.triangles[j] ) );
	
	if ( mesh.name != "" )
		meshNode.attributes.push_back( XMLAttribute( "name", toString(mesh.name) ) );
	
	meshNode.children.push_back( getNodeForTransform( mesh.transform ) );
	
	writeFile( fileName, meshNode.toString() );
}





Scene flattenScene( const Scene& scene )
{
	std::vector<Mesh> meshes = scene.meshes;
	
	for ( size_t i = 0; i < scene.instances.size(); i++ )
	{
		for ( size_t j = 0; j < scene.meshResources.size(); j++ )
		{
			if ( scene.instances[i].sourceName == scene.meshResources[j].name )
			{
				Transform transform = scene.meshResources[j].transform;
				
				// add the instance mesh transformations to the mesh.
				for ( size_t k = 0; k < scene.instances[i].transform.nodes.size(); k++ )
					transform.nodes.push_back( scene.instances[i].transform.nodes[k] );
				
				meshes.push_back( Mesh( scene.meshResources[j].triangles, transform, "" ) );
			}
		}
		
		for ( size_t j = 0; j < scene.meshes.size(); j++ )
		{
			if ( scene.instances[i].sourceName == scene.meshes[j].name )
			{
				Transform transform = scene.meshes[j].transform;
				
				// add the instance mesh transformations to the mesh.
				for ( size_t k = 0; k < scene.instances[i].transform.nodes.size(); k++ )
					transform.nodes.push_back( scene.instances[i].transform.nodes[k] );
				
				meshes.push_back( Mesh( scene.meshes[j].triangles, transform, "" ) );
			}
		}
	}
	
	return Scene( scene.camera, meshes, scene.meshResources,
				  scene.spheres, scene.lights, scene.directionalLights, scene.spotLights,
				  std::vector<Instance>(), 
				  std::vector<CSGUnion>(), std::vector<CSGDifference>(), std::vector<CSGIntersection>());
}


/// End namespace "scene"
};

